#ifndef RTDECLIENT_H
#define RTDECLIENT_H

#include <memory>
#include <vector>
#include <map>
#include <atomic>
#include "BaseClient.h"


namespace CURCONTROL {
class RTDEProtocol;
}

namespace CURCONTROL {

/*!
* \brief rtde客户端：负责RTDE端口的协议配方注册、启动、通信链接、寄存器数据交互等功能
*/
class RTDEClient : public BaseClient
{
public:
    /*!
   * \brief rtde状态枚举
   */
    enum class ConnectionState
    {
        DISCONNECTED = 0,
        CONNECTED = 1,
        STARTED = 2,
        PAUSED = 3
    };
private:
    ConnectionState conn_state_;// 链接状态
    std::atomic_bool recipeSetupState_;// 注册状态
    struct Versions {
        using RawVersions = std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>;
        void operator=(const RawVersions &raw) {
            major = std::get<0>(raw);
            minor = std::get<1>(raw);
            bugfix = std::get<2>(raw);
            build = std::get<3>(raw);
        }
        uint32_t major{0};
        uint32_t minor{0};
        uint32_t bugfix{0};
        uint32_t build{0};
    } versions_;// UR软件版本
    uint32_t frequency_;// 控制频率
    bool sendEnable_;// 发送命令使能标志

public:
    RTDEClient();
    ~RTDEClient() override;
    /*!
   * \brief 获取机械臂的控制频率
   */
    inline uint32_t GetFrequency() const{
        return frequency_;
    }

    /*!
   * \brief 与客户端重新链接
   *
   * \returns 链接成功返回true
   */
    bool Reconnect() override;
    /*!
   * \brief 与机械臂建立RTDE链接
   *
   * \param[in] 机械臂ip
   *
   * \returns 链接成功返回true
   */
    bool Connect(const std::string& robotIp);
    /*!
   * \brief 查询RTDE是否启动状态
   *
   * \returns 已启动返回true
   */
    bool IsStarted() const;
    /*!
   * \brief 发送协议命令
   */
    void Send(const RTDEProtocol &command);
    /*!
   * \brief 启动RTDE流程
   */
    void Run();
    /*!
   * \brief 修改控制使能标志
   *
   * \param[in] 是否使能
   */
    void SetSendEnable(bool enable);
private:
    /*!
   * \brief 复位自身状态
   */
    void Clear() override;
    /*!
   * \brief 启动RTDE
   */
    void SendStart();
    /*!
   * \brief 注册RTDE配方
   *
   */
    void SetupRecipes();
    /*!
   * \brief 发送RTDE输出配方
   *
   */
    void SendOutputSetup(const std::vector<std::string> &outNames);
    /*!
   * \brief 发送RTDE输入配方
   *
   */
    void SendInputSetup(const std::vector<std::string> &inNames);
    /*!
   * \brief 获取版本号
   */
    void GetControllerVersion();
    /*!
   * \brief 商定RTDE具体协议
   */
    void NegotiateProtocolVersion();
    /*!
   * \brief 发送数据
   *
   * \param[in] 命令类型
   * \param[in] 发送的负载数据
   */
    void SendAll(uint8_t command, const std::string &payload);
    /*!
   * \brief 接收数据
   */
    void Receive();
};

}// namespace CURCONTROL


#endif // RTDECLIENT_H
